"""
The MIT License (MIT)
Copyright © 2020 Walkline Wang (https://walkline.wang)
https://gitee.com/walkline/esp32-ble
"""
import ubluetooth as bt
import struct
from utime import sleep_ms
import gc
from ble.ble_hid import BLE_HID
from keyboard.keypad_matrix import KeyPad
from keyboard.utils import KeyUtils
from led.ledpad_matrix import LedPad
from hardware.v026.keycode_tables import KeycodeTables


class MyKeyPad(object):
	def __init__(self):
		self.__ble = bt.BLE()
		self.__hid = BLE_HID(self.__ble)
		self.__ledpad = None
		self.__keypad = None

		self.__keypad_layer = 0
		self.__keypad_layer_table = None
		self.__modifier = 0b0
		self.__key_codes = [0x0 for i in range(6)]
		self.__key_count = 0
		
		self.__init_ledpad()
		self.__init_keypad()

		self.__load_settings()

		self.__ledpad.start()
		self.__keypad.capture()

	@property
	def keypad_layer(self):
		return self.__keypad_layer
	
	@keypad_layer.setter
	def keypad_layer(self, value):
		self.__keypad_layer = value
		self.__keypad_layer_table = KeycodeTables.KEYPAD_LAYERS[self.__keypad_layer]
		print("keypad layer switch to {}".format(self.keypad_layer))

	def __load_settings(self):
		self.__keypad_layer_table = KeycodeTables.KEYPAD_LAYERS[0]
		self.__ledpad.brightness = LedPad.Brightness.HIGH
		self.__ledpad.mode = LedPad.Mode.BREATH

	def __init_ledpad(self):
		ROW_SET = (5, 17, 16, 4, 15) # for output
		COLUMN_SET = (22, 21, 19, 18) # for intput
		PIN_SET = (ROW_SET, COLUMN_SET)

		self.__ledpad = LedPad(PIN_SET)
		print("LedPad led count:", self.__ledpad.get_led_count())

	def __init_keypad(self):
		ROW_SET = (27, 14, 12, 13, 23) # for output
		COLUMN_SET = (32, 33, 25, 26) # for intput
		PIN_SET = (ROW_SET, COLUMN_SET)

		self.__keypad = KeyPad(PIN_SET, self.__key_down_cb, self.__key_up_cb)
		print("Keypad key count:", self.__keypad.get_key_count())

	def __key_down_cb(self, row, column):
		if row == 0: # control area key down
			return

		keycode = self.__keypad_layer_table[row][column]

		# Ctrl Alt之类的控制键
		# if keycode in KeyCharTables.CONTROL_CHAR_TABLE.values():
		# 	bit_pos = tuple(KeyCharTables.CONTROL_CHAR_TABLE.values()).index(keycode)
		# 	self.__modifier |= 1 << bit_pos

		# 支持同时 6 键
		if self.__key_count > 6:
			return

		index = self.__key_codes.index(0x0)
		self.__key_codes[index] = keycode
		self.__key_count += 1
		print("[DOWN] keycodes: {}, count: {}".format(self.__key_codes, self.__key_count))

		self.__hid.send_key_down(self.__key_codes, self.__modifier)

	def __key_up_cb(self, row, column):
		if row == 0: # control area key up
			self.keypad_layer = column
			return

		keycode = self.__keypad_layer_table[row][column]

		# Ctrl Alt之类的控制键
		if keycode in KeyCharTables.CONTROL_CHAR_TABLE.values():
			bit_pos = tuple(KeyCharTables.CONTROL_CHAR_TABLE.values()).index(keycode)
			self.__modifier &= ~(1 << bit_pos)

		index = self.__key_codes.index(keycode)
		self.__key_codes[index] = 0x0
		self.__key_count -= 1
		print("[UP] keycodes: {}, count: {}".format(self.__key_codes, self.__key_count))

		self.__hid.send_key_up(self.__key_codes, self.__modifier)


if __name__ == "__main__":
	try:
		keypad = MyKeyPad()
	except KeyboardInterrupt:
		print("\nPRESS CTRL+D TO RESET DEVICE")
